home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks '96 / MenuMadness / Source / C Source / MenuSelect.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-21  |  10.3 KB  |  476 lines  |  [TEXT/CWIE]

  1. #include <LowMem.h>
  2. #include <Menus.h>
  3. #include <stdlib.h>
  4. #include <QDOffscreen.h>
  5. #include <string.h>
  6. #include "QDUtils.h"
  7. #include "DefaultMDEF.h"
  8. #include "MenuSelect.h"
  9.  
  10.  
  11. //#define YEHUDI 1
  12.  
  13.  
  14. #ifdef YEHUDI
  15. #include "PlayNotes.h"
  16. #endif
  17.  
  18. Boolean        gTranslucent = true;
  19. GWorldPtr    gScreenBuffer = nil;
  20. CGrafPtr    gScreenPort = nil;
  21.  
  22. typedef struct    
  23. {
  24.     Rect            titleRect, menuRect;
  25.     char            menuTitle[256];
  26.     MenuHandle        menuHandle;
  27.     short            menuID;
  28.     MenuDefProcPtr    proc;
  29. }OurMenuInformation;
  30.  
  31.  
  32. #pragma options align=mac68k
  33. typedef struct
  34. {
  35.     MenuHandle    menuOH;     //handle to menu's menu record}
  36.     short        menuLeft;    // pixel location of left edge }
  37.                                         // of this menu}
  38. }MenuRec;
  39.  
  40.  
  41. typedef struct
  42. {
  43.     short         lastMenu;    // offset to last pull-down menu}
  44.     short        lastRight;    // pixel location of right edge }
  45.                             // of rightmost menu in menu bar}
  46.     short        mbResID;    // upper 13 bits are the resource ID of menu}
  47.     MenuRec        menuArray[1];
  48. }HackMListTop;
  49.  
  50. #pragma options align=reset
  51.  
  52. OSErr    ShowMenu(    OurMenuInformation    *info, GWorldPtr    screenBuffer, MenuFX    showFX);
  53.  
  54. OSErr    HideMenu(    OurMenuInformation    *info,  short    chosenItem, 
  55.                     GWorldPtr    screenBuffer,    MenuFX    hideFX);
  56. OSErr    TrackMenu(    OurMenuInformation    *info, Point    where, short    *inItem);
  57. void    InvertMenuTitle(OurMenuInformation    *info);
  58.  
  59. void EraseMenuRect(Rect    *r)
  60. {
  61.     if (gTranslucent)
  62.         {
  63.         Rect    r2 = *r;
  64.         OffsetRect(&r2, 1, 1);
  65.         QDNormal();
  66.         SetRGBForeColor(0x7777, 0x7777,0x7777);
  67.         SetRGBBackColor(0xEEEE, 0xEEEE,0xEEEE);
  68.         CopyBits(    (BitMap*)*gScreenBuffer->portPixMap, 
  69.                     (BitMap*)*gScreenPort->portPixMap, &r2, r, srcCopy, nil);
  70.         QDNormal();
  71.         }
  72.     else
  73.         EraseRect(r);
  74. }
  75.  
  76.  
  77. static int    RangedRdm(int    min, int max)
  78. {
  79.     return ((Random() * ((max + 1) - min)) >> 15) + min;
  80. }
  81.  
  82. static Boolean    PointInMenuTitle(    Point    where,         OurMenuInformation*    info, 
  83.                                     int        menuCount,     int *which)
  84. {
  85.     int    x;
  86.     
  87.     
  88.     for(x = 0 ; x < menuCount ; x++)
  89.         if (PtInRect(where, &info[x].titleRect))
  90.             {
  91.             *which = x;
  92.             return true;
  93.             }
  94.             
  95.     return false;
  96. }
  97.  
  98.  
  99.  
  100. long    AltMenuSelect(Point    where, MenuFX    showFX, MenuFX    hideFX)
  101. {
  102.     OSErr            result = noErr;
  103.     HackMListTop    **menuList = (HackMListTop**) LMGetMenuList();
  104.     int                menuCount = 0;
  105.     int                x;
  106.     OurMenuInformation    *menuInfo = nil;
  107.     Rect            menuBarRect, screenRect;
  108.     short            chosenMenu = 0, chosenItem = 0;
  109.     long            returnValue = 0;
  110.     short            menuBarHeight = LMGetMBarHeight();
  111.     CGrafPtr        savePort, menuPort;
  112.     GDHandle        saveGD;
  113.     int                pulledDownMenu = -1;
  114.     GWorldPtr        screenBuffer = nil;
  115.     PixMapHandle    screenPix = GetMainDevice()[0]->gdPMap;
  116.     /*Handle            mdef = GetResource('MDEF', 0);
  117.     
  118.     DetachResource(mdef);
  119.     HLockHi(mdef);*/
  120.     
  121.     GetGWorld(&savePort, &saveGD);
  122.     
  123.     screenRect = GetMainDevice()[0]->gdRect;
  124.     
  125. #ifdef YEHUDI
  126.     SetupPlaying();
  127. #endif
  128.     
  129.     if (result = NewGWorld(    &screenBuffer,     screenPix[0]->pixelSize,
  130.                             &screenRect,     screenPix[0]->pmTable, nil, useTempMem))
  131.         {
  132.         if (result = NewGWorld(    &screenBuffer,     screenPix[0]->pixelSize,
  133.                             &screenRect,     screenPix[0]->pmTable, nil, 0))
  134.             goto bail;
  135.         }
  136.         
  137.     
  138.     
  139.     LockPixels(screenBuffer->portPixMap);
  140.     SetGWorld(screenBuffer, nil);
  141.     ForeColor(blackColor);
  142.     BackColor(whiteColor);
  143.     CopyBits(    (BitMap*)*screenPix, (BitMap*)*screenBuffer->portPixMap, 
  144.                 &screenRect, &screenRect, srcCopy, nil);
  145.     
  146.     
  147.     GetCWMgrPort(&menuPort);
  148.     
  149.     gScreenBuffer = screenBuffer;
  150.     gScreenPort = menuPort;
  151.     
  152.     SetGWorld(menuPort, GetMainDevice());
  153.     ClipRect(&menuPort->portRect);
  154.     
  155.     menuBarRect = GetMainDevice()[0]->gdRect;
  156.     menuBarRect.bottom = menuBarRect.top + menuBarHeight;
  157.     
  158.     menuCount = (menuList[0]->lastMenu /*-12*/) / 6;
  159.     
  160.     menuInfo = (OurMenuInformation    *) NewPtrClear(sizeof(OurMenuInformation)*menuCount);
  161.  
  162.     TextFont(0);
  163.     TextSize(0);
  164.     
  165.     for(x = 0 ; x < menuCount ; x++)
  166.         {
  167.         Rect        r;
  168.         Str255        menuName;
  169.         MenuHandle    thisMenuHandle = menuList[0]->menuArray[x].menuOH;
  170.         
  171.         BlockMoveData(    &thisMenuHandle[0]->menuData[0], &menuName[0],
  172.                         thisMenuHandle[0]->menuData[0] + 1);
  173.                             
  174.         p2cstr(menuName);
  175.          
  176.         r.top = 0;
  177.         r.bottom = 20;
  178.         r.left = menuList[0]->menuArray[x].menuLeft;
  179.         r.right = r.left + stringwidth((char*)menuName) + 13;
  180.         
  181.         menuInfo[x].titleRect = r;
  182.         strcpy((char*)menuInfo[x].menuTitle, (char*)menuName);
  183.         menuInfo[x].menuHandle = thisMenuHandle;
  184.         menuInfo[x].menuID = thisMenuHandle[0]->menuID;
  185.         
  186.         
  187.         menuInfo[x].proc = DefaultMDEF;
  188.         //menuInfo[x].proc = (MenuDefProcPtr)*mdef;
  189.         }
  190.     
  191.     while(Button())
  192.         {
  193.         int    foundMenu;
  194.         Boolean    inMenuBar = false, inMenuTitle = false;
  195.         
  196.         GetMouse(&where);
  197.         
  198.     #ifdef YEHUDI
  199.         PlayANote(where.v);
  200.     #endif
  201.         
  202.         inMenuBar = PtInRect(where, &menuBarRect);
  203.         
  204.         if (inMenuBar)
  205.             {
  206.             inMenuTitle = PointInMenuTitle(where, menuInfo, menuCount, &foundMenu);
  207.         
  208.             if ((pulledDownMenu != -1) && (inMenuBar == true && inMenuTitle == false) 
  209.                                     || (inMenuTitle == true) && (foundMenu != pulledDownMenu))
  210.                 {                                             // remove pulled down menu                
  211.                 InvertMenuTitle(&menuInfo[pulledDownMenu]);
  212.                 HideMenu(&menuInfo[pulledDownMenu], 0, screenBuffer, kFXNone/*hideFX*/);
  213.                 pulledDownMenu = -1;
  214.                 }
  215.                 
  216.             if ((pulledDownMenu == -1) && (inMenuTitle == true)) // put up a new menu
  217.                 {
  218.                 pulledDownMenu = foundMenu;
  219.                 InvertMenuTitle(&menuInfo[pulledDownMenu]);
  220.                 ShowMenu(&menuInfo[pulledDownMenu], screenBuffer, showFX);
  221.                 }
  222.             }
  223.             
  224.         if (pulledDownMenu != -1) // there is a menu, so track it
  225.             {
  226.             TrackMenu(&menuInfo[pulledDownMenu], where, &chosenItem);
  227.             
  228.             if (chosenItem)
  229.                 chosenMenu = pulledDownMenu;
  230.             }
  231.         }
  232.     
  233.     if (pulledDownMenu != -1)
  234.         {
  235.         HideMenu(&menuInfo[pulledDownMenu], chosenItem, screenBuffer, hideFX);
  236.  
  237.         InvertMenuTitle(&menuInfo[pulledDownMenu]);
  238.         }
  239.     
  240.     if (chosenItem)
  241.         {
  242.         returnValue = menuInfo[pulledDownMenu].menuID;
  243.         returnValue = (returnValue << 16)  | chosenItem;
  244.         }
  245.     
  246. bail:
  247.     #ifdef YEHUDI
  248.     StopPlaying();
  249.     #endif
  250.  
  251.     if (screenBuffer != nil)
  252.         DisposeGWorld(screenBuffer);
  253.         
  254.     if (menuInfo != nil)
  255.         DisposePtr((Ptr)menuInfo);
  256.  
  257.     SetGWorld(savePort, saveGD);
  258.     
  259.     return returnValue;
  260. }
  261.  
  262. void InvertMenuTitle(OurMenuInformation    *info)
  263. {
  264.     Rect        r = info->titleRect;
  265.     
  266.     r.bottom--;
  267.     InvertRect(&r);
  268. }
  269.  
  270. static void UpdateMenuRect(OurMenuInformation    *info)
  271. {
  272.  
  273.     Rect        r = {0,0,0,0}, screenRect;
  274.     short        inItem = 0;
  275.     MenuHandle    menuHandle = info->menuHandle;
  276.  
  277.     r.top = 20;
  278.     r.left = info->titleRect.left + 1;
  279.     r.bottom = r.top + menuHandle[0]->menuHeight;
  280.     r.right = r.left + menuHandle[0]->menuWidth;
  281.     
  282.     screenRect = GetMainDevice()[0]->gdRect;
  283.     
  284.     if (r.right > screenRect.right)
  285.         OffsetRect(&r, screenRect.right - r.right, 0);
  286.                     
  287.     info->menuRect = r;
  288.  
  289. }
  290.  
  291. static void    DrawMenuBackground(OurMenuInformation    *info, Rect    r)
  292. {
  293.     
  294.     ForeColor(blackColor);
  295.     BackColor(whiteColor);
  296.  
  297.     EraseMenuRect(&r);
  298.     InsetRect(&r, -1,-1);
  299.     FrameRect(&r);
  300.     
  301.     /*
  302.     MoveTo(r.right, r.top + 2);
  303.     LineTo(r.right, r.bottom);
  304.     LineTo(r.left + 2, r.bottom);*/
  305. }
  306.  
  307. OSErr    ShowMenu(OurMenuInformation    *info, GWorldPtr    screenBuffer, MenuFX    showFX)
  308. {
  309.     OSErr        result = noErr;
  310.     Rect        r = {0,0,0,0};
  311.     short        inItem = 0;
  312.     Point        where = {0,0};
  313.     MenuHandle    menuHandle = info->menuHandle;
  314.     CGrafPtr    savePort;
  315.     GDHandle    saveGD;
  316.     
  317.     GetGWorld(&savePort, &saveGD);
  318.         
  319.         
  320.     (info->proc)(mSizeMsg, menuHandle, 
  321.                 &r, where, &inItem);
  322.                     
  323.     UpdateMenuRect(info);
  324.  
  325.                     
  326.     switch(showFX)
  327.         {
  328.         default:
  329.         case kFXNone:
  330.             DrawMenuBackground(info, info->menuRect);
  331.                             
  332.             (info->proc) (mDrawMsg, menuHandle, &info->menuRect, where, &inItem);
  333.             break;
  334.         
  335.         /*case kFXIrisOpen:
  336.             
  337.             break;*/
  338.         case kFXSlide:
  339.             {
  340.             GWorldPtr    fxGW = nil;
  341.             Rect        mRect = info->menuRect;
  342.             int            x;
  343.             int            iterations = 18; 
  344.             int            xDelta = - 16;//RangedRdm(0, 64) - 32;
  345.             int            yDelta = -16;//RangedRdm(0, 64) - 32;
  346.             Boolean        clipped = false;
  347.             Rect        nonMenubarRect = GetMainDevice()[0]->gdRect;
  348.  
  349.             nonMenubarRect.top = 20;
  350.             ClipRect(&nonMenubarRect);
  351.             
  352.             OffsetRect(&mRect, -xDelta * iterations, -yDelta * iterations);
  353.             for(x = 0 ; x <= iterations ; x++)
  354.                 {
  355.                 QDNormal();
  356.                 
  357.                 DrawMenuBackground(info, mRect);
  358.                                 
  359.                 (info->proc) (mDrawMsg, menuHandle, &mRect, where, &inItem);
  360.                 OffsetRect(&mRect, xDelta, yDelta);
  361.                 }
  362.                 
  363.             QDNormal();
  364.             SetGWorld(savePort, saveGD);
  365.             CopyBits((BitMap*)*screenBuffer->portPixMap,
  366.                     (BitMap*)*savePort->portPixMap, 
  367.                     &screenBuffer->portRect,&screenBuffer->portRect,
  368.                     srcCopy, nil);
  369.             DrawMenuBackground(info, info->menuRect);                            
  370.             (info->proc) (mDrawMsg, menuHandle, &info->menuRect, where, &inItem);
  371.  
  372.             ClipRect(&savePort->portRect);
  373.             }
  374.             break;
  375.         }
  376.     
  377.     ForeColor(blackColor);
  378.     BackColor(whiteColor);
  379.  
  380.     SetGWorld(savePort, saveGD);
  381.     return result;
  382. }
  383.  
  384.  
  385. OSErr    HideMenu(    OurMenuInformation    *info,  short    chosenItem, 
  386.                     GWorldPtr    screenBuffer,    MenuFX    hideFX)
  387. {
  388.     OSErr        result = noErr;
  389.     Rect        menuRect;
  390.     int            x;
  391.     Rect        r = screenBuffer->portRect;
  392.     GWorldPtr    fxGW = nil;        
  393.     Rect        fxRect;
  394.     CGrafPtr    savePort;
  395.     GDHandle    saveGD;
  396.         
  397.     GetGWorld(&savePort, &saveGD);
  398.         
  399.     menuRect = info->menuRect;
  400.     menuRect.right += 3;
  401.     menuRect.left -= 2;
  402.     menuRect.bottom += 2;
  403.     
  404.     QDNormal();
  405.     
  406.     if (chosenItem == 0)
  407.         hideFX = kFXNone;
  408.     
  409.     switch(hideFX)
  410.         {
  411.         default:
  412.         case kFXNone:
  413.             CopyBits((BitMap*)*screenBuffer->portPixMap, (BitMap*)*GetMainDevice()[0]->gdPMap,
  414.                     &menuRect, &menuRect, srcCopy, nil);
  415.             break;
  416.         case kFXZoomIn:
  417.         case kFXZoomOut:
  418.             {
  419.             fxRect = menuRect;
  420.             ZeroRect(&fxRect);
  421.             if (result = NewGWorld(    &fxGW, screenBuffer->portPixMap[0]->pixelSize,
  422.                                     &fxRect, nil, nil, useTempMem))
  423.                 if (result = NewGWorld(    &fxGW, screenBuffer->portPixMap[0]->pixelSize,
  424.                                     &fxRect, nil, nil, useTempMem))
  425.                     goto bail;
  426.                 
  427.             
  428.             QDNormal();
  429.             
  430.             CopyBits((BitMap*)*savePort->portPixMap,(BitMap*)*fxGW->portPixMap,
  431.                         &menuRect, &fxRect, srcCopy, nil);
  432.  
  433.             if (hideFX == kFXZoomOut)
  434.                 for (x = 0 ; x < 20 ; x++)
  435.                     {
  436.                     InsetRect(&menuRect, 8, 4 );
  437.                     CopyBits((BitMap*)*fxGW->portPixMap,(BitMap*)*savePort->portPixMap,
  438.                                  &fxRect, &menuRect,ditherCopy, nil);
  439.                     }
  440.             else
  441.                 for (x = 0 ; x < 10 ; x++)
  442.                     {                        
  443.                     InsetRect(&menuRect, -(x + 1) * 88, -(x + 1) * 44);
  444.                     CopyBits((BitMap*)*fxGW->portPixMap,(BitMap*)*savePort->portPixMap,
  445.                                  &fxRect, &menuRect,srcCopy, nil);
  446.                     }
  447.                 
  448.                 
  449.             CopyBits((BitMap*)*screenBuffer->portPixMap, (BitMap*)*GetMainDevice()[0]->gdPMap,
  450.                     &r, &r, srcCopy, nil);        
  451.             break;
  452.             }
  453.             
  454.         }
  455.  
  456.  
  457. bail:
  458.  
  459.     if (fxGW)
  460.         DisposeGWorld(fxGW);
  461.  
  462.     SetGWorld(savePort, saveGD);
  463.  
  464.     return result;
  465. }
  466.  
  467.  
  468. OSErr    TrackMenu(    OurMenuInformation    *info, Point    where, short    *inItem)
  469. {
  470.     OSErr    result = noErr;
  471.     
  472.     (info->proc) (mChooseMsg, info->menuHandle, &info->menuRect, where, inItem);
  473.     
  474.     return result;
  475. }
  476.